﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX.Direct3D10_1;
using SlimDX.Direct3D10;
using SlimDX.Direct3D9;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;

namespace System.Windows.Media.Media3D10
{
    internal static class Engine
    {
        [DllImport("user32.dll", SetLastError = false)]
        [SuppressMessage("Microsoft.Design", "CA1060")]
        private static extern IntPtr GetDesktopWindow();

        private static DeviceEx _device9;

        private static Device1 _device10;

        internal static DeviceEx Device9 
        { 
            get 
            {
                if (_device9 == null) Initialize();
                return _device9; 
            } 
        }

        internal static Device1 Device10 
        { 
            get
            {
                if (_device10 == null) Initialize();
                return _device10; 
            }
        }

        private static void Initialize()
        {
            Application.Current.Exit += (s, e) =>
                {
                    int count = SlimDX.ObjectTable.Objects.Count;
                    for (int i = 0; i < count; i++)
                    {
                        SlimDX.ComObject item = SlimDX.ObjectTable.Objects[0];
                        if (item != null)
                        {
                            item.Dispose();
                            item = null;
                        }
                    }
                };
            _device9 = CreateDevice9();
            _device10 = CreateDevice10();
        }

        private static DeviceEx CreateDevice9()
        {
            DeviceEx temp = null;
            DeviceEx returnValue = null;

            try
            {
                using (Direct3DEx d3dContext = new Direct3DEx())
                {
                    PresentParameters presentparams = new PresentParameters();
                    presentparams.Windowed = true;
                    presentparams.SwapEffect = SwapEffect.Discard;
                    presentparams.Multisample = MultisampleType.None;
                    presentparams.DeviceWindowHandle = GetDesktopWindow();
                    presentparams.PresentationInterval = PresentInterval.Immediate;

                    temp = new DeviceEx(d3dContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams);
                }
                returnValue = temp;
                temp = null;
            }
            finally
            {
                if (temp != null)
                {
                    temp.Dispose();
                    temp = null;
                }
            }

            return returnValue;
        }

        private static Device1 CreateDevice10()
        {
            Device1 device = null;
            Device1 temp = null;
            try
            {
                temp = new Device1(DriverType.Hardware, DeviceCreationFlags.Debug | DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0);
                temp.Flush();
                device = temp;
                temp = null;
            }
            finally
            {
                if (temp != null)
                {
                    temp.Dispose();
                    temp = null;
                }
            }
            return device;
        }
    }
}
